//! 命名服务核心数据模型

use nacos_core::ServiceInstance;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};

/// 服务定义 - 代表一个逻辑服务
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Service {
    /// 服务名
    pub name: String,
    /// 分组名
    pub group_name: String,
    /// 命名空间
    pub namespace: String,
    /// 保护阈值
    pub protect_threshold: f32,
    /// 选择器类型
    pub selector_type: SelectorType,
    /// 选择器表达式
    pub selector_expression: Option<String>,
    /// 元数据
    pub metadata: HashMap<String, String>,
    /// 集群列表
    pub clusters: Vec<String>,
}

impl Service {
    /// 创建新的服务
    pub fn new(
        name: String,
        group_name: String,
        namespace: String,
    ) -> Self {
        Self {
            name,
            group_name,
            namespace,
            protect_threshold: 0.0,
            selector_type: SelectorType::None,
            selector_expression: None,
            metadata: HashMap::new(),
            clusters: vec!["DEFAULT".to_string()],
        }
    }

    /// 获取服务的唯一标识
    pub fn get_key(&self) -> String {
        format!("{}#{}#{}" , self.namespace, self.group_name, self.name)
    }

    /// 添加集群
    pub fn add_cluster(&mut self, cluster_name: String) {
        if !self.clusters.contains(&cluster_name) {
            self.clusters.push(cluster_name);
        }
    }

    /// 移除集群
    pub fn remove_cluster(&mut self, cluster_name: &str) {
        self.clusters.retain(|c| c != cluster_name);
    }
}

/// 选择器类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum SelectorType {
    /// 无选择器
    None,
    /// 标签选择器
    Label,
    /// 条件选择器
    Condition,
    /// 自定义选择器
    Custom,
}

/// 服务状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ServiceStatus {
    /// 服务名
    pub service_name: String,
    /// 分组名
    pub group_name: String,
    /// 命名空间
    pub namespace: String,
    /// 总实例数
    pub total_instance_count: usize,
    /// 健康实例数
    pub healthy_instance_count: usize,
    /// 触发保护阈值
    pub trigger_protect: bool,
    /// 集群状态
    pub cluster_status: HashMap<String, ClusterStatus>,
}

/// 集群状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ClusterStatus {
    /// 集群名
    pub cluster_name: String,
    /// 总实例数
    pub total_instance_count: usize,
    /// 健康实例数
    pub healthy_instance_count: usize,
    /// 健康检查状态
    pub health_check_status: HealthCheckStatus,
}

/// 健康检查状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum HealthCheckStatus {
    /// 未开启
    None,
    /// 开启中
    Running,
    /// 暂停
    Paused,
    /// 停止
    Stopped,
}

/// 实例管理器 - 管理一个服务下的所有实例
#[derive(Debug, Clone)]
pub struct InstanceManager {
    instances: HashMap<String, ServiceInstance>,
}

impl InstanceManager {
    /// 创建新的实例管理器
    pub fn new() -> Self {
        Self {
            instances: HashMap::new(),
        }
    }

    /// 添加或更新实例
    pub fn add_instance(&mut self, instance: ServiceInstance) {
        self.instances.insert(instance.instance_id.clone(), instance);
    }

    /// 移除实例
    pub fn remove_instance(&mut self, instance_id: &str) {
        self.instances.remove(instance_id);
    }

    /// 获取实例
    pub fn get_instance(&self, instance_id: &str) -> Option<&ServiceInstance> {
        self.instances.get(instance_id)
    }

    /// 获取所有实例
    pub fn get_all_instances(&self) -> Vec<&ServiceInstance> {
        self.instances.values().collect()
    }

    /// 获取健康实例
    pub fn get_healthy_instances(&self) -> Vec<&ServiceInstance> {
        self.instances
            .values()
            .filter(|instance| instance.healthy && instance.enabled)
            .collect()
    }

    /// 获取集群下的实例
    pub fn get_instances_by_cluster(&self, cluster_name: &str) -> Vec<&ServiceInstance> {
        self.instances
            .values()
            .filter(|instance| instance.cluster_name == cluster_name)
            .collect()
    }

    /// 获取集群下的健康实例
    pub fn get_healthy_instances_by_cluster(&self, cluster_name: &str) -> Vec<&ServiceInstance> {
        self.instances
            .values()
            .filter(|instance| {
                instance.cluster_name == cluster_name && instance.healthy && instance.enabled
            })
            .collect()
    }

    /// 获取实例数量
    pub fn get_instance_count(&self) -> usize {
        self.instances.len()
    }

    /// 获取健康实例数量
    pub fn get_healthy_instance_count(&self) -> usize {
        self.instances
            .values()
            .filter(|instance| instance.healthy && instance.enabled)
            .count()
    }

    /// 检查服务是否触发保护阈值
    pub fn is_trigger_protect(&self, threshold: f32) -> bool {
        if threshold <= 0.0 {
            return false;
        }
        
        let total = self.get_instance_count();
        if total == 0 {
            return false;
        }
        
        let healthy = self.get_healthy_instance_count();
        let healthy_ratio = healthy as f32 / total as f32;
        healthy_ratio < (1.0 - threshold)
    }
}

/// 服务注册表 - 管理所有服务及其实例
#[derive(Debug, Clone)]
pub struct ServiceRegistry {
    services: HashMap<String, Service>,
    instance_managers: HashMap<String, InstanceManager>,
}

impl ServiceRegistry {
    /// 创建新的服务注册表
    pub fn new() -> Self {
        Self {
            services: HashMap::new(),
            instance_managers: HashMap::new(),
        }
    }

    /// 注册服务
    pub fn register_service(&mut self, service: Service) {
        let key = service.get_key();
        self.services.insert(key.clone(), service);
        self.instance_managers.insert(key, InstanceManager::new());
    }

    /// 注销服务
    pub fn deregister_service(&mut self, namespace: &str, group: &str, service_name: &str) {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        self.services.remove(&key);
        self.instance_managers.remove(&key);
    }

    /// 获取服务
    pub fn get_service(&self, namespace: &str, group: &str, service_name: &str) -> Option<&Service> {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        self.services.get(&key)
    }

    /// 注册实例
    pub fn register_instance(&mut self, instance: ServiceInstance) {
        let key = format!("{}#{}#{}" , instance.namespace, instance.group_name, instance.service_name);
        
        // 确保服务存在
        if !self.services.contains_key(&key) {
            let service = Service::new(
                instance.service_name.clone(),
                instance.group_name.clone(),
                instance.namespace.clone(),
            );
            self.register_service(service);
        }

        // 注册实例到对应的服务
        if let Some(manager) = self.instance_managers.get_mut(&key) {
            manager.add_instance(instance);
        }
    }

    /// 注销实例
    pub fn deregister_instance(&mut self, namespace: &str, group: &str, service_name: &str, instance_id: &str) {
        let key = format!("{}#{}#{}", namespace, group, service_name);
        
        if let Some(manager) = self.instance_managers.get_mut(&key) {
            manager.remove_instance(instance_id);
        }
    }

    /// 获取实例
    pub fn get_instance(&self, namespace: &str, group: &str, service_name: &str, instance_id: &str) -> Option<&ServiceInstance> {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        self.instance_managers
            .get(&key)
            .and_then(|manager| manager.get_instance(instance_id))
    }

    /// 获取所有实例
    pub fn get_all_instances(&self, namespace: &str, group: &str, service_name: &str) -> Vec<&ServiceInstance> {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        self.instance_managers
            .get(&key)
            .map(|manager| manager.get_all_instances())
            .unwrap_or_default()
    }

    /// 获取健康实例
    pub fn get_healthy_instances(&self, namespace: &str, group: &str, service_name: &str) -> Vec<&ServiceInstance> {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        self.instance_managers
            .get(&key)
            .map(|manager| manager.get_healthy_instances())
            .unwrap_or_default()
    }

    /// 获取所有服务名
    pub fn get_all_service_names(&self, namespace: &str, group: Option<&str>) -> Vec<String> {
        use std::collections::HashSet;
        
        let mut unique_names = HashSet::new();
        self.services
            .values()
            .filter(|service| {
                service.namespace == namespace &&
                group.map_or(true, |g| service.group_name == g)
            })
            .for_each(|service| {
                unique_names.insert(service.name.clone());
            });
        
        let mut result: Vec<String> = unique_names.into_iter().collect();
        result.sort(); // Ensure consistent ordering for tests
        result
    }

    /// 获取服务状态
    pub fn get_service_status(&self, namespace: &str, group: &str, service_name: &str) -> Option<ServiceStatus> {
        let key = format!("{}#{}#{}" , namespace, group, service_name);
        
        let service = self.services.get(&key)?;
        let manager = self.instance_managers.get(&key)?;

        let total_instance_count = manager.get_instance_count();
        let healthy_instance_count = manager.get_healthy_instance_count();
        let trigger_protect = manager.is_trigger_protect(service.protect_threshold);

        let mut cluster_status = HashMap::new();
        for cluster_name in &service.clusters {
            let cluster_instances = manager.get_instances_by_cluster(cluster_name);
            let healthy_cluster_instances = manager.get_healthy_instances_by_cluster(cluster_name);
            
            cluster_status.insert(
                cluster_name.clone(),
                ClusterStatus {
                    cluster_name: cluster_name.clone(),
                    total_instance_count: cluster_instances.len(),
                    healthy_instance_count: healthy_cluster_instances.len(),
                    health_check_status: HealthCheckStatus::Running,
                },
            );
        }

        Some(ServiceStatus {
            service_name: service.name.clone(),
            group_name: service.group_name.clone(),
            namespace: service.namespace.clone(),
            total_instance_count,
            healthy_instance_count,
            trigger_protect,
            cluster_status,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use nacos_core::ServiceInstance;

    #[test]
    fn test_service_creation() {
        let service = Service::new(
            "test-service".to_string(),
            "test-group".to_string(),
            "public".to_string(),
        );

        assert_eq!(service.name, "test-service");
        assert_eq!(service.group_name, "test-group");
        assert_eq!(service.namespace, "public");
        assert_eq!(service.protect_threshold, 0.0);
        assert_eq!(service.selector_type, SelectorType::None);
    }

    #[test]
    fn test_instance_manager() {
        let mut manager = InstanceManager::new();
        let instance = ServiceInstance::new(
            "test-service".to_string(),
            "test-group".to_string(),
            "127.0.0.1".to_string(),
            8080,
        );

        manager.add_instance(instance.clone());
        assert_eq!(manager.get_instance_count(), 1);
        assert_eq!(manager.get_healthy_instance_count(), 1);

        let retrieved = manager.get_instance(&instance.instance_id);
        assert_eq!(retrieved.unwrap().instance_id, instance.instance_id);
    }

    #[test]
    fn test_service_registry() {
        let mut registry = ServiceRegistry::new();
        let instance = ServiceInstance::new(
            "test-service".to_string(),
            "test-group".to_string(),
            "127.0.0.1".to_string(),
            8080,
        );

        registry.register_instance(instance.clone());
        
        let instances = registry.get_all_instances("public", "test-group", "test-service");
        assert_eq!(instances.len(), 1);
        assert_eq!(instances[0].instance_id, instance.instance_id);

        let services = registry.get_all_service_names("public", Some("test-group"));
        assert_eq!(services.len(), 1);
        assert_eq!(services[0], "test-service");
    }
}